package com.liziba.classloader;

import sun.nio.ch.Net;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;

/**
 * <p>
 *      网络类加载器
 * </p>
 *
 * @Author: Liziba
 * @Date: 2021/5/31 23:25
 */
public class NetworkClassLoader extends ClassLoader{

    /** 指定网络URL */
    private String rootUrl;

    public NetworkClassLoader(String rootUrl) {
        this.rootUrl = rootUrl;
    }


    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] classData = getClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        } else {
            return defineClass(name, classData, 0, classData.length);
        }
    }


    /**
     * 从网络上获取类的字节数组
     *
     * @param className
     * @return
     */
    private byte[] getClassData(String className) {

        String path = classNameCovertToPath(className);
        try {
            URL url = new URL(path);
            InputStream ins = url.openStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024 * 4];
            int len = 0;
            // 读取类文件的字节
            while ((len = ins.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            return baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 类权限定名转绝对路径
     *
     * @param className
     * @return
     */
    private String classNameCovertToPath(String className) {

        return rootUrl + "/"
                + className.replace('.', '/') + ".class";
    }
}
